#include <iostream>
#include <fstream>
#include <algorithm>
#include "table.h"
#include "scanner.h"
#include <cctype>
#include <unordered_map>
#include <unordered_set>
#include <string>
Table init_table();

int main()
{
    // ifstream fin("/mnt/d/codefile/code_cpp/CPP_Multiple/C_Scanner/test.c", ios_base::in);
    unordered_set<string> keys = {
        "main", "if", "int", "for", "while", "do", "return", "break", "continue"
    };

    Scanner scanner(init_table());
    try
    {
        // if(!fin)
        //     throw "can not read file";
        
        auto tokens = scanner.do_scan(cin);
        for (auto &t : tokens)
            if(t.kind == 2 && keys.find(t.token) != keys.end())
                t.kind = 1;
        for(const auto&t : tokens)
            cout << t << '\n';
        
    }
    catch(const string &e)
    {
        cerr << e << '\n';
        return 3;
    }

    return 0;
}

Table init_table()
{
    Tuple tmp;
    tmp.fill(-1);
    vector<Tuple> table(11, tmp);
    // 0
    for (char c = 'a'; c <= 'z'; ++c)
        table[0][c] = 1;
    for (char c = 'A'; c <= 'Z'; ++c)
        table[0][c] = 1;
    table[0]['_'] = 1;
    for (char c = '0'; c <= '9'; ++c)
        table[0][c] = 3;

    vector<char> tmp1 = {'+', '-', '*', '/', '='};
    for (const char &c : tmp1)
        table[0][c] = 5;

    tmp1 = {'<', '>'};
    for (const char &c : tmp1)
        table[0][c] = 6;

    table[0]['!'] = 8;

    tmp1 = {',', ';', '{', '}', '(', ')'};
    for (const char &c : tmp1)
        table[0][c] = 10;
    // 1
    for (unsigned char c = 0; c < ASCII_SIZE; ++c)
    {
        if (c == '_' || isalnum(c))
            table[1][c] = 1;
        else
            table[1][c] = 2;
    }
    // 3
    for (unsigned char c = 0; c < ASCII_SIZE; ++c)
    {
        if (isdigit(c))
            table[3][c] = 3;
        else if (!isalpha(c) && c != '_')
            table[3][c] = 4;
    }
    // 6
    for (unsigned char c = 0; c < ASCII_SIZE; ++c)
    {
        if (c == '=')
            table[6][c] = 7;
        else
            table[6][c] = 5;
    }
    // 8
    table[8]['='] = 9;
    Function fun = [](int u, char c, const vector<Tuple> &_table) -> pair<int, bool>
    {
        const static unordered_map<int, int> endmap = {{2, 2}, {4, 3}, {5, 4}, {7, 4}, {9, 4}, {10, 5}};
        int ne = _table[u][c];
        auto it = endmap.find(ne);
        if (it != endmap.end())
        {
            bool jump;
            switch (ne)
            {
            case 2:
            case 4:
                jump = false;
                break;
            case 7:
            case 9:
            case 10:
                jump = true;
                break;

            case 5:
                if (u == 0)
                    jump = true;
                else if (u == 6)
                    jump = false;
                break;
            }
            return {it->second, jump};
        }
        return {-1, true};
    };

    return Table(table, fun);
}